from matplotlib.pyplot import text
from numpy.lib.arraypad import pad
from testgear2 import calcx1
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
from tkinter import ttk
import datetime
from invfun import inv, inv_1
from math import sin, cos, tan, radians, degrees, floor, sqrt, acos, atan, pi
from gear import Gear, GearInit, PlanetaryGear, PlanetInit, PrintToTxt, gongfaxian, liangzhu
import huichacalc as hc
import ctypes
import gongcha as gc
import os
import opt
import numpy as np
import helicalstiffness
import tkinter.messagebox
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import random
# 模块化的GUI


class NumVar(StringVar):  # 继承StringVar类并添加成员函数，用于消除get和set的BUG，本质将数值用字符串来保存和读取
    def get(self):

        try:
            try:
                res = int(str(self._tk.globalgetvar(self._name)))  # 先尝试整型数转换
            except:
                # 如果不是整型数则尝试转化为浮点数
                res = float(str(self._tk.globalgetvar(self._name)))
            return res
        except:
            self.set(value='0')
            return 0

    def set(self, value):  # 重写set函数，加入str(value)
        return self._tk.globalsetvar(self._name, str(value))


class GlobalGearSetting(object):  # 除了齿轮数据之外的设置数据
    def __init__(self, check_2_var=True, check_3_var=True,
                 Fr=True, fxfy=True, carrier_pt=False,
                 fa=False, autosavelog=True):
        self.check_2_var = BooleanVar(value=check_2_var)
        self.check_3_var = BooleanVar(value=check_3_var)

        self.Fr = BooleanVar(value=Fr)  # 径跳or径综
        self.fxfy = BooleanVar(value=fxfy)  # 是否计算平行度偏差

        # 后续可能加入的影响，先设置
        self.carrier_pt = BooleanVar(value=carrier_pt)  # 是否考虑行星架节距偏差****
        self.fa = BooleanVar(value=fa)  # 是否考虑轴承游隙
        self.autosavelog = BooleanVar(value=autosavelog)  # 是否自动保存日志（计算之后）


class FrameGearVars(object):  # 都是全局variable变量Var
    def __init__(self, alpha_deg=20, ha_std=1, c_std=0.25, x1calc='auto', beta_deg=0,
                 m=0.0, zlist=[0, 0, 0], xlist=[0.0, 0.0, 0.0], blist=[0.0, 0.0, 0.0], itlist=[6, 6, 7], EbEylist=['Eb', 'Eb', 'Ey'],
                 Elist=[0.0, 0.0, 0.0], Eslist=[0.0, 0.0, 0.0], Eilist=[0.0, 0.0, 0.0],
                 Klist=[0, 0, 0], Dmlist=[0.0, 0.0, 0.0],
                 dfa_si=[0, 0],
                 inputfaOrNot='auto'):
        self.x1calc = StringVar(value=x1calc)  # 这行是stringvar，用于checkbutton
        self.inputfaOrNot = StringVar(value=inputfaOrNot)

        self.alpha_deg = NumVar(value=alpha_deg)
        self.ha_std = NumVar(value=ha_std)
        self.c_std = NumVar(value=c_std)
        self.m = NumVar(value=m)
        self.beta = NumVar(value=beta_deg)
        self.dfa_si = [NumVar(value=dfax) for dfax in dfa_si]  # 中心距公差
        # 以下是list(3)
        self.zlist = [NumVar(value=zx) for zx in zlist]
        self.xlist = [NumVar(value=xx) for xx in xlist]
        self.blist = [NumVar(value=bx) for bx in blist]
        self.itlist = [NumVar(value=itx) for itx in itlist]
        # 这行是stringvar，用于radiobutton
        self.EbEylist = [StringVar(value=EbEyx) for EbEyx in EbEylist]
        self.Elist = [NumVar(value=Ex) for Ex in Elist]
        self.Eslist = [NumVar(value=Esx) for Esx in Eslist]
        self.Eilist = [NumVar(value=Eix) for Eix in Eilist]
        self.Klist = [NumVar(value=Kx) for Kx in Klist]
        self.Dmlist = [NumVar(value=Dmx) for Dmx in Dmlist]


def commonFrame(parent, row=0, column=0,  columnspan=1, rowspan=1, padding=(3, 3, 12, 12), sticky=(N, S, E, W)):
    frame = ttk.Frame(parent, padding=padding)
    frame.grid(column=column, row=row, columnspan=columnspan,
               rowspan=rowspan, sticky=sticky, pady=5, padx=5)
    return frame


def textFrame(parent, text='',  row=0, column=0, columnspan=1, rowspan=1, padding=(3, 3, 12, 12), style='TLabelframe'):
    labelframe = ttk.LabelFrame(
        parent, text=text, padding=padding, style=style)
    labelframe.grid(column=column, row=row, columnspan=columnspan,
                    rowspan=rowspan, sticky=(N, S, E, W), pady=5, padx=5)
    return labelframe


def numEntry(parent, var: NumVar,  row=0, column=0, columnspan=1, rowspan=1, width=8, state='normal', style='TEntry'):
    entry = ttk.Entry(parent, width=width, textvariable=var,
                      state=state, style=style)
    entry.grid(column=column, row=row, columnspan=columnspan,
               rowspan=rowspan, sticky=(N, S, E, W), pady=3, padx=3)
    return entry


def textLabel(parent, text='', row=0, column=0,  columnspan=1, rowspan=1, state='normal', style='TLabel'):
    label = ttk.Label(parent, text=text, state=state, style=style)
    label.grid(column=column, row=row, columnspan=columnspan,
               rowspan=rowspan, sticky=(N, S, E, W), pady=3, padx=3)
    return label


class GearGUI(object):
    def __init__(self, rootname='GearGUI_HC_calc'):

        self.root = Tk()  # 主窗口
        # self.root.geometry("2000x2000")
        ctypes.windll.shcore.SetProcessDpiAwareness(1)  # 适配高分辨率
        ScaleFactor = ctypes.windll.shcore.GetScaleFactorForDevice(0)
        self.root.tk.call('tk', 'scaling', ScaleFactor/75)
        self.root.option_add("*Font", ("宋体", 12))
        self.root.title(rootname)
        self.s = ttk.Style()
        # self.s.theme_use('winnative')
        self.s.theme_use('vista')
        self.s.configure('.', font=("宋体", 12))
        # self.s.configure('TEntry',font=("宋体",12))
        # self.s.configure('TCheckbutton',font=("宋体",12))
        # self.s.configure('TLabelframe',font=("宋体",12))
        # self.s.configure('TRadiobutton',font=("宋体",12))
        self.s.configure('Red.TLabel', foreground='red')
        self.s.configure('fileread.TLabel',
                         background='white', font=("宋体", 12))

        nb = ttk.Notebook(self.root)
        nb.grid(column=0, row=0, sticky=(N, S, E, W))

        firstframe = ttk.Frame(nb, padding=(3, 3, 12, 12))
        firstframe.grid(column=0, row=0, sticky=(N, S, E, W))

        nb.add(firstframe, text='回差计算')

        secondframe = ttk.Frame(nb, padding=(3, 3, 12, 12))
        secondframe.grid(column=0, row=0, sticky=(N, S, E, W))

        nb.add(secondframe, text='参数优化')

        
        thirdframe = ttk.Frame(nb, padding=(3, 3, 12, 12))
        thirdframe.grid(column=0, row=0, sticky=(N, S, E, W))

        nb.add(thirdframe, text='啮合刚度计算')
        
        self.thirdtabgui(thirdframe)
        
        self.secondtabgui(secondframe)  # 放置参数优化栏

        # 主框架firstframe中的部件插入

        self.setting = GlobalGearSetting()  # 加载全局设置

        # 2、3级是否激活
        self.check_2_frame = commonFrame(
            firstframe, 0, 3, padding=(0, 0, 0, 0), sticky=(N, W))
        self.check_3_frame = commonFrame(
            firstframe, 0, 4, padding=(0, 0, 0, 0), sticky=(N, W))
        self.check_2 = ttk.Checkbutton(self.check_2_frame, text='第二级', variable=self.setting.check_2_var, onvalue=True, offvalue=False,
                                       command=self.check_2and3)
        self.check_2.grid(row=0, column=0, sticky=(N, S, E, W), pady=3, padx=3)
        self.check_3 = ttk.Checkbutton(self.check_3_frame, text='第三级', variable=self.setting.check_3_var, onvalue=True, offvalue=False,
                                       command=self.check_2and3)
        self.check_3.grid(row=0, column=0, sticky=(N, S, E, W), pady=3, padx=3)

        self.label_2 = textLabel(
            self.check_2_frame, '', 1, 0, style='Red.TLabel')
        self.label_3 = textLabel(
            self.check_3_frame, '', 1, 0, style='Red.TLabel')

        # 各级行星齿轮框架(假设是3级)
        self.frame_gear = [textFrame(firstframe, '第一级(输入级)参数', 1, 0, columnspan=2),
                           textFrame(firstframe, '第二级参数', 1, 2, columnspan=2),
                           textFrame(firstframe, '第三级参数', 1, 4, columnspan=2)]
        self.gearvar = [FrameGearVars(), FrameGearVars(),
                        FrameGearVars()]  # 建立各级齿轮数据包
        # 用于存储需要改变state的entry（此处为变位系数x，其实只需要x1，但是为了代码整洁和后续可能的扩展，把变位系数entry都加入）
        self.entry_x1_list = [[], [], []]
        self.check_fa_list = []
        self.entry_fa_list = [[], [], []]
        self.entry_K_list = [[], [], []]  # 用于存储需要改变state的entry（此处为公法线跨齿数K）
        self.entry_Dm_list = [[], [], []]  # 用于存储需要改变state的entry（此处为量柱球直径Dm）
        for j in range(len(self.gearvar)):
            self.gear_place(self.frame_gear[j], self.gearvar[j], j)  # 建立齿轮框架内容

        # 单独检查x1 entry的state状态并设置
        self.check_x1()

        # 建立公差frame
        self.frame_gc = textFrame(firstframe, '公差选项', 2, 0, 2)
        self.gc_place(self.frame_gc)

        # 建立计算frame
        self.frame_calc = textFrame(firstframe, '计算', 2, 2)
        self.calc_place(self.frame_calc)

        # 建立Text Frame
        self.frame_text = commonFrame(
            firstframe, 2, 3, 3, padding=(0, 0, 0, 0), sticky=(N, W))
        self.text_place(self.frame_text)
        self.PrintText.configure(state='disable')

        # 建立载入文件
        self.frame_load = commonFrame(
            firstframe, 0, 0, 3, padding=(3, 3, 3, 3))
        self.load_place(self.frame_load)

        #
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)

        firstframe.columnconfigure(0, weight=1)
        firstframe.columnconfigure(1, weight=1)
        firstframe.columnconfigure(2, weight=1)
        firstframe.columnconfigure(3, weight=1)
        firstframe.columnconfigure(4, weight=1)
        firstframe.columnconfigure(5, weight=1)
        firstframe.rowconfigure(0, weight=0)
        firstframe.rowconfigure(1, weight=0)
        firstframe.rowconfigure(2, weight=1)

        for i in range(3):
            self.frame_gear[i].columnconfigure(0, weight=3)
            self.frame_gear[i].columnconfigure(1, weight=1)
            self.frame_gear[i].columnconfigure(2, weight=1)
            self.frame_gear[i].columnconfigure(3, weight=1)

        ##########################################################
        # 开发测试按钮
        self.s.configure('Test.TButton', foreground='red')
        textbutton = ttk.Button(firstframe, text='test',
                                command=self.test, style='Test.TButton')
        textbutton.grid(column=5, row=0, sticky=(N, W), pady=3, padx=3)

        # 主窗口循环刷新
        self.root.mainloop()

    def thirdtabgui(self,parent):
        self.typelist = ['-', '--', ':', '-.']
        self.colorlist = ['red', 'orange', 'green', 'blue', 'black']
        self.j = 0
        
        inputframe1 = ttk.Labelframe(parent,padding=(3, 3, 12, 12))
        inputframe1.grid(row=0,column=0,padx=5,pady=5,sticky=(N, S, E, W))
        
        ttk.Label(inputframe1,text='端面重合度',width=8).grid(row=0,column=0,padx=3,pady=3,sticky=(N, S, E, W))
        self.epa = NumVar(value=1.5)
        ttk.Entry(inputframe1,textvariable=self.epa,width=8).grid(row=0,column=1,padx=3,pady=3,sticky=(N, S, E, W))
        
        ttk.Label(inputframe1,text='纵向重合度',width=8).grid(row=1,column=0,padx=3,pady=3,sticky=(N, S, E, W))
        self.epb = NumVar(value=1)
        ttk.Entry(inputframe1,textvariable=self.epb,width=8).grid(row=1,column=1,padx=3,pady=3,sticky=(N, S, E, W))
        
        ttk.Button(inputframe1,text='单独显示时变啮合刚度',command=lambda: self.draw(self.epa.get(),self.epb.get(),clear=True)).grid(row=2,column=0,padx=3,pady=3,sticky=(N, S, E, W))
        ttk.Button(inputframe1,text='继续显示时变啮合刚度',command=lambda: self.draw(self.epa.get(),self.epb.get(),clear=False)).grid(row=3,column=0,padx=3,pady=3,sticky=(N, S, E, W))
        
        
        ttk.Label(inputframe1,text='显示的y轴范围\n(用于调整视野)',width=8).grid(row=4,column=0,padx=3,pady=3,sticky=(N, S, E, W))
        self.ylimmax = NumVar(value=2)
        self.ylimmin = NumVar(value=0.5)
        ttk.Entry(inputframe1,textvariable=self.ylimmin,width=10).grid(row=4,column=1,padx=3,pady=3,sticky=(N, S, E, W))
        ttk.Entry(inputframe1,textvariable=self.ylimmax,width=10).grid(row=4,column=2,padx=3,pady=3,sticky=(N, S, E, W))
        ttk.Button(inputframe1,text='调整y轴',command=lambda: self.adjustylim(self.ylimmin.get(),self.ylimmax.get())).grid(row=5,column=1,padx=3,pady=3,sticky=(N, S, E, W))
        
        ttk.Button(inputframe1,text='保存图形',command=lambda: self.savestiffpic()).grid(row=6,column=0,padx=3,pady=3,sticky=(N, S, E, W))
        
        matplotframe = ttk.Frame(parent,padding=(3, 3, 12, 12))
        matplotframe.grid(row=0,column=1,padx=5,pady=5,sticky=(N, S, E, W))
        
        self.drawPic_f = Figure(figsize=(6, 4), dpi=200)

        self.drawPic_canvas = FigureCanvasTkAgg(self.drawPic_f, master=matplotframe)
        self.drawPic_canvas.draw()
        self.drawPic_canvas.get_tk_widget().grid(row=0, column=0)
        self.drawPic_a = self.drawPic_f.add_subplot(111)
    
    def draw(self,epa,epb,clear=True):
        if epa>0 and epb>=0:
            
            if clear:
                self.drawPic_f.clf()
                self.drawPic_a = self.drawPic_f.add_subplot(111)
                self.drawPic_a.set_xlabel('$\\xi$')
                self.drawPic_a.set_ylabel('$K/K_{max}$')
                self.drawPic_a.set_title('Stiffness/Kmax')
                self.drawPic_a.grid()
            
            elist = np.arange(0, epa+epb, 0.005)
            KallList=[]
            for e in elist:
                KallList.append(helicalstiffness.KL_h(e, epa, epb, 1, 0, ak=0.8))
            
            ymin = self.ylimmin.get()
            ymax = self.ylimmax.get()
            yminc,ymaxc=min([ymin,ymax]),max([ymin,ymax])
            self.drawPic_a.set_ylim([yminc,ymaxc])
            self.drawPic_a.plot(elist,KallList,self.typelist[self.j % len(self.typelist)],color=self.colorlist[self.j % len(self.colorlist)],
                                label='$ep_{a,b}=%.2f,%.2f$' % (epa,epb))
            self.drawPic_a.annotate('(%.2f,%.2f)' % (epa,epb), xy=(random.uniform(0,epa+epb), max(KallList)+0.02), color=self.colorlist[self.j % len(self.colorlist)], size=7)
            self.drawPic_a.legend(fontsize=8,title_fontsize=8)
            self.drawPic_canvas.draw()
            
            self.j+=1
    
    def savestiffpic(self):
        filepath = filedialog.asksaveasfilename(title='选择保存文件路径和名称', filetypes=[(
            'PNG', '.png')], initialdir='.\\', defaultextension='.png', initialfile='stiffpic.png')
        if filepath:
            #inputfilepath = filepath[0:-4]+'_inputfile.txt'
            #with open(filepath, 'w', encoding='utf-8') as f:
            try:
                self.drawPic_canvas.print_png(filepath)
                tkinter.messagebox.showinfo(title='保存图片', message='保存成功至'+filepath)
            except:
                tkinter.messagebox.showwarning(title='保存图片', message='未能保存'+filepath)
            
            #self.drawPic_a.savefig(filepath, dpi=400, bbox_inches='tight')
    
    def adjustylim(self,ymin,ymax):
        yminc,ymaxc=min([ymin,ymax]),max([ymin,ymax])
        self.drawPic_a.set_ylim([yminc,ymaxc])
        self.drawPic_canvas.draw()
    
    def calc(self):  # 计算总回差
        def printf(char, end='\n'):
            self.printf(char=char, end=end)
        if self.PrintText.get(1.0, "end") != '\n':  # 空
            printf('')
        else:
            self.printtime()
        printf('>>Start Calculating...')

        # 逻辑判断+计算公称齿厚
        if self.setting.check_2_var.get() == False:
            jrange = 1  # 只有一级齿轮
        else:
            if self.setting.check_3_var.get() == False:
                jrange = 2  # 两级齿轮
            else:
                jrange = 3  # 三级齿轮
        printf(f'>>共有{jrange}级行星齿轮')

        K = [[None, None, None], [None, None, None], [None, None, None]]
        Dm = [[None, None, None], [None, None, None], [None, None, None]]

        # 初始化矩阵
        ptinitlist = []
        ptlist = []
        inputEbEy = []

        # 控制输出齿轮基本参数的参数n
        n = 7

        for j in range(jrange):  # 第j级齿轮
            if self.gearvar[j].alpha_deg.get() > 0 and\
                    self.gearvar[j].ha_std.get() > 0 and\
                    self.gearvar[j].c_std.get() > 0 and\
                    self.gearvar[j].m.get() > 0 and\
                    self.gearvar[j].zlist[0].get() > 0 and self.gearvar[j].zlist[1].get() > 0 and self.gearvar[j].zlist[2].get() > 0 and\
                    self.gearvar[j].blist[0].get() > 0 and self.gearvar[j].blist[1].get() > 0 and self.gearvar[j].blist[2].get() > 0:
                printf(f'>>第{str(0)+str(j+1)}级输入正常')
                # 判断是否自动计算x1
                if self.gearvar[j].x1calc.get() == 'auto':
                    self.gearvar[j].xlist[0].set(value=calcx1(self.gearvar[j].xlist[2].get(), self.gearvar[j].xlist[1].get(),
                                                              self.gearvar[j].zlist[0].get(), self.gearvar[j].zlist[1].get(
                    ), self.gearvar[j].zlist[2].get(),
                        radians(self.gearvar[j].alpha_deg.get()),))

                printf(
                    f'第{str(0)+str(j+1)}级齿轮基本参数:\nalpha_deg:{self.gearvar[j].alpha_deg.get():>5.2f};ha_std:{self.gearvar[j].ha_std.get():>5.2f};c_std={self.gearvar[j].c_std.get():>5.2f};m={self.gearvar[j].m.get():>5.2f};')
                printf(
                    f'{" z1, z3 ,z2 = ":>17s}{self.gearvar[j].zlist[0].get():>{n}d},{self.gearvar[j].zlist[1].get():>{n}d},{self.gearvar[j].zlist[2].get():>{n}d};')
                printf(
                    f'{" x1, x3 ,x2 = ":>17s}{self.gearvar[j].xlist[0].get():>{n}.4f},{self.gearvar[j].xlist[1].get():>{n}.4f},{self.gearvar[j].xlist[2].get():>{n}.4f};')
                printf(
                    f'{" b1, b3 ,b2 = ":>17s}{self.gearvar[j].blist[0].get():>{n}.2f},{self.gearvar[j].blist[1].get():>{n}.2f},{self.gearvar[j].blist[2].get():>{n}.2f};')
                printf(
                    f'{"it1,it3,it2 = ":>17s}{self.gearvar[j].itlist[0].get():>{n}d},{self.gearvar[j].itlist[1].get():>{n}d},{self.gearvar[j].itlist[2].get():>{n}d};')

            else:
                printf(f'Error:第{str(0)+str(j+1)}级输入错误')
                return

            # 判断是否自动计算x1
            if self.gearvar[j].x1calc.get() == 'auto':
                self.gearvar[j].xlist[0].set(value=calcx1(self.gearvar[j].xlist[2].get(), self.gearvar[j].xlist[1].get(),
                                                          self.gearvar[j].zlist[0].get(), self.gearvar[j].zlist[1].get(
                ), self.gearvar[j].zlist[2].get(),
                    radians(self.gearvar[j].alpha_deg.get()),))

            for i in range(3):  # 三个齿轮，0,1,2
                if self.gearvar[j].EbEylist[i].get() == 'Eb':  # 第j级第i个齿轮是采用公法线
                    if self.gearvar[j].Klist[i].get() == 0:  # 没有给定跨齿数
                        printf(
                            f'Warning:第{str(j+1)}级-齿轮{str(i+1)}跨齿数未给定，采用软件计算值')
                    else:  # 给定了跨齿数
                        K[j][i] = self.gearvar[j].Klist[i].get()

                else:  # 第j级第i个齿轮是采用量柱球
                    if self.gearvar[j].Dmlist[i].get() == 0:  # 没有给定量柱半径
                        printf(
                            f'Warning:第{str(j+1)}级-齿轮{str(i+1)}量柱球半径未给定，采用软件计算值')
                    else:  # 给定了量柱直径
                        Dm[j][i] = self.gearvar[j].Dmlist[i].get()

            ptinitlist.append(PlanetInit(b=[self.gearvar[j].blist[0].get(), self.gearvar[j].blist[1].get(), self.gearvar[j].blist[2].get()],
                                         it=[self.gearvar[j].itlist[0].get(), self.gearvar[j].itlist[1].get(
                                         ), self.gearvar[j].itlist[2].get()],
                                         alpha_deg=self.gearvar[j].alpha_deg.get(), ha_std=self.gearvar[j].ha_std.get(), c_std=self.gearvar[j].c_std.get(),
                                         K=K[j], Dm=Dm[j],
                                         EbEy=[self.gearvar[j].EbEylist[0].get(), self.gearvar[j].EbEylist[1].get(), self.gearvar[j].EbEylist[2].get()]))

            ptlist.append(PlanetaryGear(self.gearvar[j].m.get(),
                                        self.gearvar[j].zlist[0].get(), self.gearvar[j].zlist[1].get(
            ), self.gearvar[j].zlist[2].get(),
                self.gearvar[j].xlist[0].get(), self.gearvar[j].xlist[1].get(
            ), self.gearvar[j].xlist[2].get(),
                ptinitlist[j], beta_deg=self.gearvar[j].beta.get()
            ))

            # ptlist[j].gear_ac.PrintAllItem()
            # ptlist[j].gear_cb.PrintAllItem()

            inputEbEy.append(hc.InputEb(self.gearvar[j].Eslist[0].get(), self.gearvar[j].Eilist[0].get(),
                                        self.gearvar[j].Eslist[1].get(
            ), self.gearvar[j].Eilist[1].get(),
                self.gearvar[j].Eslist[2].get(
            ), self.gearvar[j].Eilist[2].get(),
                Emeasure=[self.gearvar[j].EbEylist[0].get(), self.gearvar[j].EbEylist[1].get(), self.gearvar[j].EbEylist[2].get()]))

            # 将计算出的E、K、Dm写入GUI
            for i in range(3):
                self.gearvar[j].Elist[i].set(value=ptlist[j].E[i])
                if self.gearvar[j].EbEylist[i].get() == 'Eb':
                    self.gearvar[j].Klist[i].set(value=ptlist[j].K[i])
                else:
                    self.gearvar[j].Dmlist[i].set(value=ptlist[j].Dm[i])

            printf(
                f'{"":>17s}{self.gearvar[j].EbEylist[0].get():>{n}s},{self.gearvar[j].EbEylist[1].get():>{n}s},{self.gearvar[j].EbEylist[2].get():>{n}s};（公法线Eb/量柱球Ey）')
            printf(
                f'{" E1, E3, E2 = ":>17s}{self.gearvar[j].Elist[0].get():>{n}.2f},{self.gearvar[j].Elist[1].get():>{n}.2f},{self.gearvar[j].Elist[2].get():>{n}.2f};（公法线/量柱球测量距公称值）(mm)')
            printf(
                f'{"Es1,Es3,Es2 = ":>17s}{self.gearvar[j].Eslist[0].get():>{n}d},{self.gearvar[j].Eslist[1].get():>{n}d},{self.gearvar[j].Eslist[2].get():>{n}d};（公法线/量柱球测量距上偏差）(um)')
            printf(
                f'{"Ei1,Ei3,Ei2 = ":>17s}{self.gearvar[j].Eilist[0].get():>{n}d},{self.gearvar[j].Eilist[1].get():>{n}d},{self.gearvar[j].Eilist[2].get():>{n}d};（公法线/量柱球测量距下偏差）(um)')
            printf(
                f'{" K1, K3  K2 = ":>17s}{self.gearvar[j].Klist[0].get():>{n}d},{self.gearvar[j].Klist[1].get():>{n}d},{self.gearvar[j].Klist[2].get():>{n}d};（公法线跨齿数）')
            printf(
                f'{"Dm1,Dm3,Dm2 = ":>17s}{self.gearvar[j].Dmlist[0].get():>{n}.2f},{self.gearvar[j].Dmlist[1].get():>{n}.2f},{self.gearvar[j].Dmlist[2].get():>{n}.2f};（量柱球直径）(mm)')

        falist = []
        for j in range(jrange):
            falist.append(self.setting.fa.get())
        dfalist = []
        if self.setting.fa.get():  # 如果为True，即启用中心距公差
            for j in range(jrange):
                # 判断是手动输入还是自动决定
                if self.gearvar[j].inputfaOrNot.get() != 'auto':  # 手动输入
                    dfalist.append([self.gearvar[j].dfa_si[0].get(),
                                    self.gearvar[j].dfa_si[1].get()])
                else:  # 自动决定，调用f_a函数

                    printf(f'Warning:第{str(j+1)}级中心距误差未给定（或未选中手动输入选项），采用软件计算值')
                    Tfa = gc.f_a(ptlist[j].gear_ac.a_work,
                                 min([ptlist[j].PlanetInitStruct.it1, ptlist[j].PlanetInitStruct.it2, ptlist[j].PlanetInitStruct.it3]))

                    dfalist.append([Tfa/2, -Tfa/2])

                    self.gearvar[j].dfa_si[0].set(value=Tfa/2)
                    self.gearvar[j].dfa_si[1].set(value=-Tfa/2)
                    # dfalist.append([])#用于表示未指定，需要程序计算
                printf(
                    f'{"    fas,fai = ":>17s}{"":>6s} {self.gearvar[j].dfa_si[0].get():>6.2f},{self.gearvar[j].dfa_si[1].get():>6.2f}.（中心距上下偏差）(um)')
        else:  # 没启用中心距公差
            for j in range(jrange):
                dfalist.append([])

        pthclist_si, pthclist_si_divide_i, allhc = hc.pthc2allhc(ptlist=ptlist, Ebinlist=inputEbEy, carrier=self.setting.carrier_pt.get(),
                                                                 Fr=self.setting.Fr.get(), fxfy=self.setting.fxfy.get(), returneverycx=True,
                                                                 falist=falist, dfalist=dfalist)

        # print(len(pthclist_si))
        space = '\u3000'  # 全角空格，用于对齐中文
        printf("------------------------")
        printf(">>RESULT:")

        if self.setting.Fr.get():
            printf("√ 径向跳动误差Fr")
        else:
            printf("× 径向跳动误差Fr")

        if self.setting.fxfy.get():
            printf("√ 轴线平行度误差fxfy")
        else:
            printf("× 轴线平行度误差fxfy")

        if self.setting.carrier_pt.get():
            if not self.setting.fa.get():
                printf("√ 行星架节距误差carrier_pt(中心距误差未考虑，此项无影响)")
            else:
                printf("√ 行星架节距误差carrier_pt")
        else:
            printf("× 行星架节距误差carrier_pt")

        if self.setting.fa.get():
            printf("√ 中心距误差fa")
        else:
            printf("× 中心距误差fa")

        for j in range(jrange):
            printf(
                f"{f'第{str(0)+str(j+1)}级回差':{space}<9s}{'最大值：':>4s}{'':4s}{pthclist_si[j][0]:>6.3f}{'(arcmin)':<14s}{pthclist_si[j][0]/60:>6.4f}(°)"
            )
            printf(
                f"{'最小值：':{space}>12s}{'':4s}{pthclist_si[j][1]:>6.3f}{'(arcmin)':<14s}{pthclist_si[j][1]/60:>6.4f}(°)"
            )
            printf(
                f"{'(折算的最大值)：':{space}>13s}{'[':>4s}{pthclist_si_divide_i[j][0]:>6.3f}{'(arcmin)':<14s}{pthclist_si_divide_i[j][0]/60:>6.4f}(°)]"
            )
            printf(
                f"{'(折算的最小值)：':{space}>13s}{'[':>4s}{pthclist_si_divide_i[j][1]:>6.3f}{'(arcmin)':<14s}{pthclist_si_divide_i[j][1]/60:>6.4f}(°)]"
            )

        printf(
            f"{'行星轮系总回差':{space}<8s}{'最大值：':>4s}{'':4s}{allhc[0]:>6.3f}{'(arcmin)':<14s}{allhc[0]/60:>6.4f}(°)")
        printf(
            f"{'平均值：':{space}>12s}{'':4s}{(allhc[1]+allhc[0])/2:>6.3f}{'(arcmin)':<14s}{(allhc[1]+allhc[0])/2/60:>6.4f}(°)")
        printf(
            f"{'最小值：':{space}>12s}{'':4s}{allhc[1]:>6.3f}{'(arcmin)':<14s}{allhc[1]/60:>6.4f}(°)")

        if self.setting.autosavelog.get() == True:
            self.savelog('auto')

    def gearload(self):  # 用于读取外部文件，后续扩展，load函数内容
        # self.gearvar[0].x1calc.set(inputvar.x1calc.get())
        if self.PrintText.get(1.0, "end") != '\n':  # 空
            self.printf('')
        else:
            self.printtime()
        self.printf('>>选择Input文件...')
        filepath = filedialog.askopenfilename(
            title='选择数据文件', filetypes=[('TXT', '.txt')], initialdir='.\\')
        if filepath:  # 读取到了文件
            self.printf('>>已选择文件'+filepath)
            self.filereadtext.set(value=filepath)
            # 判断能否读取文件，尝试读取
            with open(filepath, 'r', encoding='utf-8') as f:
                try:
                    gearvardicts = list(self.gearvar[0].__dict__.items())
                    settingdicts = list(self.setting.__dict__.items())
                    for j in range(len(self.gearvar)):  # 第j级行星齿轮
                        for i in range(len(gearvardicts)):  # 每个gearvar的行i
                            wholeline = f.readline()
                            line = wholeline.replace('\n', '').replace(
                                ',', '\t').split('\t')
                            if i < 7:
                                self.gearvar[j].__dict__[line[0]].set(line[1])
                            elif i == 7:
                                self.gearvar[j].__dict__[
                                    line[0]][0].set(line[1])
                                self.gearvar[j].__dict__[
                                    line[0]][1].set(line[2])
                            else:
                                self.gearvar[j].__dict__[
                                    line[0]][0].set(line[1])
                                self.gearvar[j].__dict__[
                                    line[0]][1].set(line[2])
                                self.gearvar[j].__dict__[
                                    line[0]][2].set(line[3])
                    for i in range(len(settingdicts)):
                        wholeline = f.readline()
                        line = wholeline.replace('\n', '').split('\t')
                        if line[1] == 'True':
                            self.setting.__dict__[line[0]].set(True)
                        elif line[1] == 'False':
                            self.setting.__dict__[line[0]].set(False)
                    self.printf('>>文件载入成功')
                except:
                    self.printf('Error:文件载入失败或中断')

        else:  # 没有读取到文件
            self.printf('Error:没有选择文件')
            self.filereadtext.set(value='没有选择文件')
        self.check()  # 执行check，state检查

    def gearsave(self):  # 用于存储数据文件
        if self.PrintText.get(1.0, "end") != '\n':  # 空
            self.printf('')
        else:
            self.printtime()
        self.printf('>>选择文件保存路径...')
        filepath = filedialog.asksaveasfilename(title='选择保存文件路径和名称', filetypes=[(
            'TXT', '.txt')], initialdir='.\\', defaultextension='.txt', initialfile='defaultsave.txt')
        if filepath:
            #inputfilepath = filepath[0:-4]+'_inputfile.txt'

            with open(filepath, 'w', encoding='utf-8') as f:
                for j in range(3):
                    gearvardicts = list(self.gearvar[j].__dict__.items())
                    for i in range(len(gearvardicts)):
                        if i < 7:  # 6取决于是否是list
                            # f.write('%s\t%s\n'%(gearvardicts[i][0],str(gearvardicts[i][1].get())))
                            f.write(
                                f'{gearvardicts[i][0]}\t{gearvardicts[i][1].get()}\n')
                        elif i == 7:
                            f.write(
                                f'{gearvardicts[i][0]}\t{gearvardicts[i][1][0].get()}\t{gearvardicts[i][1][1].get()}\n')

                        else:
                            # f.write('%s\t%s\t%s\t%s\n'%(gearvardicts[i][0],str(gearvardicts[i][1][0].get()),str(gearvardicts[i][1][1].get()),str(gearvardicts[i][1][2].get())))
                            f.write(
                                f'{gearvardicts[i][0]}\t{gearvardicts[i][1][0].get()}\t{gearvardicts[i][1][1].get()}\t{gearvardicts[i][1][2].get()}\n')

                settingdicts = list(self.setting.__dict__.items())
                for i in range(len(settingdicts)):
                    # f.write('%s\t%s\n'%(str(settingdicts[i][0]),str(settingdicts[i][1].get())))
                    f.write(
                        f'{settingdicts[i][0]}\t{settingdicts[i][1].get()}\n')

                self.printf('>>数据文件保存成功')
        else:
            self.printf('Error:没有保存数据文件')
        pass

    def load_place(self, parent):  # load框架内容
        ttk.Button(parent, text='载入文件', command=self.gearload).grid(
            column=0, row=0, sticky=(N, S, E, W), pady=3, padx=3)
        self.filereadtext = StringVar()
        ttk.Label(parent, textvariable=self.filereadtext, width=60, style='fileread.TLabel').grid(
            column=1, row=0, sticky=(N, S, E, W), pady=3, padx=3)

    def text_place(self, parent):
        self.PrintText = Text(parent, height=15)
        self.PrintText.grid(column=0, row=0, sticky=(N, W))
        text_ys = ttk.Scrollbar(parent, orient='vertical',
                                command=self.PrintText.yview)
        self.PrintText['yscrollcommand'] = text_ys.set
        text_ys.grid(column=1, row=0, sticky=(N, S))

    def calc_place(self, parent):
        ttk.Button(parent, text='计算总回差', command=self.calc).grid(
            column=0, row=0, sticky=(N, S, E, W), pady=3, padx=3)

        ttk.Button(parent, text='清空Log', command=self.clearlog).grid(
            column=0, row=1, sticky=(N, S, E, W), pady=3, padx=3)

        ttk.Button(parent, text='保存数据', command=self.gearsave).grid(
            column=0, row=2, sticky=(N, S, E, W), pady=3, padx=3)

        ttk.Button(parent, text='保存日志和结果', command=self.savelog).grid(
            column=0, row=3, sticky=(N, S, E, W), pady=3, padx=3)

        ttk.Checkbutton(parent, text='自动保存日志文件（计算后）', variable=self.setting.autosavelog, onvalue=True,
                        offvalue=False).grid(column=0, row=4, sticky=(N, S, E, W), pady=3, padx=3)

    def gc_place(self, parent):  # 公差框架内容

        ttk.Checkbutton(parent, text='齿圈径向跳动Fr', variable=self.setting.Fr, onvalue=True,
                        offvalue=False, command=self.check_gc).grid(column=0, row=0, sticky=(N, S, E, W), pady=3, padx=3)

        # 平行度公差checkbutton
        ttk.Checkbutton(parent, text='轴线平行度公差', variable=self.setting.fxfy, onvalue=True,
                        offvalue=False, command=self.check_gc).grid(column=0, row=1, sticky=(N, S, E, W), pady=3, padx=3)

        # 行星架节距误差checkbutton
        ttk.Checkbutton(parent, text='行星架节距偏差', variable=self.setting.carrier_pt, onvalue=True,
                        offvalue=False, command=self.check_gc).grid(column=0, row=2, sticky=(N, S, E, W), pady=3, padx=3)

        # 中心距偏差

        ttk.Checkbutton(parent, text='中心距偏差', variable=self.setting.fa, onvalue=True,
                        offvalue=False, command=self.check_gc).grid(column=0, row=3, sticky=(N, S, E, W), pady=3, padx=3)

    def gear_place(self, parent, var: FrameGearVars, j):  # 齿轮数据输入框架,j:第0/1/2级行星轮

        textLabel(parent, '压力角α°', 0, 0)
        textLabel(parent, '螺旋角β°', 1, 0)
        textLabel(parent, '齿高ha*', 0, 2)
        textLabel(parent, '顶隙C*', 1, 2)
        numEntry(parent, var.alpha_deg, 0, 1)
        numEntry(parent, var.beta, 1, 1)
        numEntry(parent, var.ha_std, 0, 3)
        numEntry(parent, var.c_std, 1, 3)

        n = 2  # base
        ttk.Checkbutton(parent, text='自动计算x1', variable=var.x1calc, onvalue='auto', offvalue='manual',
                        command=self.check_x1).grid(column=2, row=n+0, columnspan=2, sticky=(N, S, E, W), pady=3, padx=3)

        textLabel(parent, 'm(模数)', n+0, 0)
        textLabel(parent, '太阳轮(1)', n+1, 1)
        textLabel(parent, '行星轮(2)', n+1, 2)
        textLabel(parent, '内齿轮(3)', n+1, 3)
        textLabel(parent, 'z(齿数)', n+2, 0)
        textLabel(parent, 'x(变位)', n+3, 0)
        textLabel(parent, 'b(齿宽)', n+4, 0)
        textLabel(parent, 'IT(精度)', n+5, 0)
        textLabel(parent, '公称长度', n+8, 0)
        textLabel(parent, '上偏差Es(um)', n+9, 0)
        textLabel(parent, '下偏差Ei(um)', n+10, 0)
        textLabel(parent, '公法线跨齿数', n+11, 0)
        textLabel(parent, '量柱直径(mm)', n+12, 0)

        numEntry(parent, var.m, n+0, 1)
        for i in range(3):
            numEntry(parent, var.zlist[i], n+2, 1+i)
            self.entry_x1_list[j].append(
                numEntry(parent, var.xlist[i], n+3, 1+i))
            numEntry(parent, var.blist[i], n+4, 1+i)
            ttk.Combobox(parent, width=8, state='readonly', textvariable=var.itlist[i], values=(
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)).grid(row=n+5, column=1+i, sticky=(N, S, E, W), pady=3, padx=3)
            ttk.Radiobutton(parent, text='公法线', variable=var.EbEylist[i], value='Eb', command=self.checkEbEy, takefocus=1).grid(
                row=n+6, column=1+i, sticky=(N, S, E, W), pady=3, padx=3)
            ttk.Radiobutton(parent, text='量柱球', variable=var.EbEylist[i], value='Ey', command=self.checkEbEy, takefocus=1).grid(
                row=n+7, column=1+i, sticky=(N, S, E, W), pady=3, padx=3)
            numEntry(parent, var.Elist[i], n+8, 1+i, state='disable')
            numEntry(parent, var.Eslist[i], n+9, 1+i)
            numEntry(parent, var.Eilist[i], n+10, 1+i)

            Eb_state, Ey_state = ['normal', 'disable'] if var.EbEylist[i].get() == 'Eb' else [
                'disable', 'normal']
            self.entry_K_list[j].append(
                numEntry(parent, var.Klist[i], n+11, 1+i, state=Eb_state))
            self.entry_Dm_list[j].append(
                numEntry(parent, var.Dmlist[i], n+12, 1+i, state=Ey_state))

        fastate = 'normal' if self.setting.fa.get() == True else 'disable'
        self.check_fa_list.append(ttk.Checkbutton(parent, text='输入中心距公差', variable=var.inputfaOrNot,
                                                  onvalue='manual', offvalue='auto', command=self.check_gc, state=fastate))

        self.check_fa_list[j].grid(
            row=n+13, column=0, sticky=(N, S, E, W), pady=3, padx=3)

        textLabel(parent, '上偏差s(um)', n+13, 1)
        textLabel(parent, '下偏差s(um)', n+14, 1)
        inputfastate = 'disable' if var.inputfaOrNot.get(
        ) == 'auto' or self.setting.fa.get() == False else 'normal'
        self.entry_fa_list[j].append(
            numEntry(parent, var.dfa_si[0], n+13, 2, state=inputfastate)
        )
        self.entry_fa_list[j].append(
            numEntry(parent, var.dfa_si[1], n+14, 2, state=inputfastate)
        )

    def check(self):
        self.checkEbEy()
        self.check_x1()
        self.check_2and3()
        self.check_gc()

    def check_2and3(self):
        if not self.setting.check_2_var.get():  # 如果第二级未激活
            self.label_2.configure(text='第2级失效')
            # self.check_3_var.set(value=False)
            self.check_3.configure(state='disable')
            self.label_3.configure(text='第3级失效')
        else:  # 第二级激活
            self.label_2.configure(text='')
            self.check_3.configure(state='normal')
            self.label_3.configure(text='', state='normal')
            if not self.setting.check_3_var.get():  # 如果第三级未激活
                self.label_3.configure(text='第3级失效')
            else:  # 第三级激活
                self.label_3.configure(text='')

    def check_x1(self):
        for j in range(len(self.gearvar)):
            x1state_tmp = 'disable' if self.gearvar[j].x1calc.get(
            ) == 'auto' else 'normal'
            self.entry_x1_list[j][0].configure(state=x1state_tmp)

    def checkEbEy(self):

        for j in range(len(self.gearvar)):  # j 第j级
            Eb_state = ['normal' if EbEyx.get(
            ) == 'Eb' else 'disable' for EbEyx in self.gearvar[j].EbEylist]
            Ey_state = ['normal' if EbEyx.get(
            ) == 'Ey' else 'disable' for EbEyx in self.gearvar[j].EbEylist]
            for i in range(3):
                self.entry_K_list[j][i].configure(state=Eb_state[i])
                self.entry_Dm_list[j][i].configure(state=Ey_state[i])

    def check_gc(self):

        for j in range(len(self.gearvar)):  # j 第j级
            inputfastate = 'disable' if self.gearvar[j].inputfaOrNot.get(
            ) == 'auto' or self.setting.fa.get() == False else 'normal'
            fastate = 'normal' if self.setting.fa.get() == True else 'disable'
            self.entry_fa_list[j][0].configure(state=inputfastate)
            self.entry_fa_list[j][1].configure(state=inputfastate)
            self.check_fa_list[j].configure(state=fastate)

    def printf(self, char, end='\n'):
        self.PrintText.configure(state='normal')
        self.PrintText.insert('end', str(char)+end)
        self.PrintText.see('end')
        self.PrintText.configure(state='disable')

    def printf2(self, char, end='\n'):
        self.PrintText2.configure(state='normal')
        self.PrintText2.insert('end', str(char)+end)
        self.PrintText2.see('end')
        self.PrintText2.configure(state='disable')

    def printtime(self, end='\n'):
        self.printf(f'[{str(datetime.datetime.today())[0:-7]}] ', end=end)

    def clearlog(self):
        self.PrintText.configure(state='normal')
        self.PrintText.delete('1.0', 'end')
        self.PrintText.configure(state='disable')
        self.filereadtext.set('')

    def savelog(self, types='manual'):  # 用于存储日志文件以及结果
        if self.PrintText.get(1.0, "end") == '\n':  # 空
            messagebox.showinfo('提示', '没有需要保存的日志')
            return
        if types == 'manual':
            self.printf('>>选择日志文件保存路径...')
            filepath = filedialog.asksaveasfilename(title='选择保存日志文件路径和名称', filetypes=[(
                'TXT', '.txt')], initialdir='.\\', defaultextension='.txt', initialfile='defaultsave_log.txt')
            if filepath:

                with open(filepath, 'w', encoding='utf-8') as f:
                    self.PrintText.configure(state='normal')
                    f.write(self.PrintText.get(1.0, "end"))
                    self.PrintText.configure(state='disable')
                    self.printf('>>已成功保存日志文件至'+filepath)

            else:
                self.printf('>>未选择保存文件')

        else:  # 'auto'
            self.printf('>>正在自动保存日志文件...')
            logdir = '.\\Log_Autosave'
            if not os.path.exists(logdir):
                os.mkdir(logdir)
            filepath = logdir+'\\autosave_log' + \
                str(datetime.datetime.today()).replace(
                    ':', "_").replace('.', '_')+'.txt'
            with open(filepath, 'w', encoding='utf-8') as f:
                self.PrintText.configure(state='normal')
                f.write(self.PrintText.get(1.0, "end"))
                self.PrintText.configure(state='disable')
                self.printf('>>已自动保存日志文件至'+filepath)

    def secondtabgui(self, parent: ttk.LabelFrame):
        self.frame_optz = textFrame(
            parent=parent, text='齿数优化：最佳啮合角', row=0, column=0)
        textLabel(parent=self.frame_optz, text='太阳轮齿数', row=0, column=0)
        textLabel(parent=self.frame_optz, text='内齿轮齿数', row=1, column=0)
        textLabel(parent=self.frame_optz, text='内齿轮齿数', row=1, column=3)
        self.optz_z1 = NumVar(value=0)
        self.optz_z2 = NumVar(value=0)
        self.optz_z3 = NumVar(value=0)

        numEntry(self.frame_optz, self.optz_z1, 0, 1)
        numEntry(self.frame_optz, self.optz_z2, 1, 1)
        numEntry(self.frame_optz, self.optz_z3, 1, 4)
        ttk.Button(self.frame_optz, text='优化行星轮齿数', command=self.optz).grid(
            column=3, row=0, columnspan=2, sticky=(N, S, E, W), pady=3, padx=3)

        frame_optx = textFrame(
            parent=parent, text='变位系数优化：最佳滑动率', row=1, column=0)

        textLabel(parent=frame_optx, text='压力角α', row=0, column=0)
        textLabel(parent=frame_optx, text='齿顶高系数ha*', row=0, column=2)
        textLabel(parent=frame_optx, text='顶隙系数C*', row=0, column=4)
        textLabel(parent=frame_optx, text='模数', row=1, column=0)
        textLabel(parent=frame_optx, text='太阳轮齿数', row=1, column=1)
        textLabel(parent=frame_optx, text='行星轮齿数', row=1, column=2)
        textLabel(parent=frame_optx, text='内齿轮齿数', row=1, column=3)

        self.optx_alpha_deg = NumVar(value=20)
        self.optx_hastd = NumVar(value=1)
        self.optx_cstd = NumVar(value=0.25)
        self.optx_m = NumVar(value=0)
        self.optx_z1 = NumVar(value=0)
        self.optx_z3 = NumVar(value=0)
        self.optx_z2 = NumVar(value=0)
        numEntry(frame_optx, self.optx_alpha_deg, 0, 1)
        numEntry(frame_optx, self.optx_hastd, 0, 3)
        numEntry(frame_optx, self.optx_cstd, 0, 5)
        numEntry(frame_optx, self.optx_m, 2, 0)
        numEntry(frame_optx, self.optx_z1, 2, 1)
        numEntry(frame_optx, self.optx_z3, 2, 2)
        numEntry(frame_optx, self.optx_z2, 2, 3)

        textLabel(parent=frame_optx, text='变位系数精度', row=0, column=6)
        textLabel(parent=frame_optx, text='【外】啮合权重', row=1, column=6)
        textLabel(parent=frame_optx, text='【内】啮合权重', row=2, column=6)

        self.optx_h = NumVar(value=0.01)
        self.optx_k1 = NumVar(value=10)
        self.optx_k2 = NumVar(value=1)

        numEntry(frame_optx, self.optx_h, 0, 7)
        numEntry(frame_optx, self.optx_k1, 1, 7)
        numEntry(frame_optx, self.optx_k2, 2, 7)

        ttk.Button(frame_optx, text='优化变位', command=self.optx).grid(
            column=4, row=1, columnspan=1, rowspan=2, sticky=(N, S, E, W), pady=3, padx=3)
        ttk.Button(frame_optx, text='清除文本', command=self.clearlog2).grid(
            column=5, row=1, columnspan=1, rowspan=2, sticky=(N, S, E, W), pady=3, padx=3)

        text2frame = commonFrame(parent, 2, 0)
        self.PrintText2 = Text(text2frame, height=15, width=100)
        self.PrintText2.grid(column=0, row=0, sticky=(N, W))
        text_ys2 = ttk.Scrollbar(text2frame, orient='vertical',
                                 command=self.PrintText2.yview)
        self.PrintText2['yscrollcommand'] = text_ys2.set
        text_ys2.grid(column=1, row=0, sticky=(N, S))

    def optz(self):
        try:
            z3 = opt.optz(self.optz_z1.get(), self.optz_z2.get())
            self.optz_z3.set(value=z3[0])
        except:
            self.optz_z3.set(value=-1)

    def optx(self):
        m = self.optx_m.get()
        z1 = self.optx_z1.get()
        z3 = self.optx_z3.get()
        z2 = self.optx_z2.get()
        h = self.optx_h.get()
        alpha = radians(self.optx_alpha_deg.get())
        hastd = self.optx_hastd.get()
        cstd = self.optx_cstd.get()
        k1 = self.optx_k1.get()
        k2 = self.optx_k2.get()
        if m <= 0 or z1 <= 0 or z3 <= 0 or z2 <= 0 or h <= 0 or hastd <= 0 or cstd <= 0 or alpha <= 0:
            self.printf2('输入错误')
            return
        elif k1 < 0 or k2 < 0:
            self.printf2('Warning: 权重为负值')

        pt_list = opt.optx(m, z1, z3, z2, np.arange(-1, 1, h), np.arange(-1, 1, h),
                          alpha, hastd, cstd, k1, k2)
        
        self.printf2('')
        for i in range(10):
            pt = pt_list[i]
            self.printf2(
                f'变位:{pt.xa:>7.4f}{pt.xc:>7.4f}{pt.xb:>7.4f};滑动率差:{pt.gear_ac.dyeta:>7.4f}{pt.gear_cb.dyeta:>7.4f};重合度{pt.gear_ac.ContactRatio:>6.3f}{pt.gear_cb.ContactRatio:>6.3f};啮合角:{degrees(pt.gear_ac.alpha_work):>6.2f}{degrees(pt.gear_cb.alpha_work):>6.2f}'
            )
        

    def clearlog2(self):
        self.PrintText2.configure(state='normal')
        self.PrintText2.delete('1.0', 'end')
        self.PrintText2.configure(state='disable')

    def test(self):

        # print(self.stdvar.c_std.set(value=0.3))
        #inputvar = FrameGearVars(x1calc='manual')
        # self.gearload(inputvar)
        print('Test--------------')
        # print(list(self.gearvar[0].__dict__.items()))
        # print(self.PrintText.get(1.0, "end")=='\n')
        #gearvardicts = str(self.gearvar[0].__dict__.items())
        # print((gearvardicts))
        '''
        with open('testdict.txt','w') as f:
            f.write(gearvardicts)
        
        with open('testdict.txt','r') as f:
            gearstrread = f.read()
            geardictread = eval(gearstrread)
            print(type(geardictread))
        '''
        self.savelog(types='auto')


if __name__ == '__main__':
    GearGUI()
